window.Player = {
    synthLoaded: false,
    init: function () {
        window.synth = SampleLibrary.load({
            instruments: "piano",
            onload: function () {
                synth = synth.toMaster();
                log('资源加载完成!');
                Player.synthLoaded = true;
            }
        });
        log('资源加载中...');
    },
    play: function (music) {
        if (!this.synthLoaded) {
            this.error('资源未加载完成');
            return;
        }
        var timeUnit = (60 * 1000) / music.speed;

        return new Promise(function play(reslove, reject) {
            var asyncTracker = new Utils.ASyncTracker("MusicPlayer", reslove);
            music.tracks.forEach((track) => {
                var r = function TrackPlayer() {
                    try {
                        if (TrackPlayer.position < TrackPlayer.track.notes.length) {
                            var note = TrackPlayer.track.notes[TrackPlayer.position][0];
                            var time = TrackPlayer.track.notes[TrackPlayer.position].length > 1 ? TrackPlayer.track.notes[TrackPlayer.position][1] : 1;
                            Player.playNoteInMusic(TrackPlayer.track.step, note, time);
                            TrackPlayer.position++;
                            setTimeout(TrackPlayer, (timeUnit * (+time)));
                        } else asyncTracker.exit();
                    } catch (err) {
                        asyncTracker.close();
                        reject(err);
                    }
                }
                r.position = 0;
                r.track = track;
                asyncTracker.enter();
                r();
            });
        });
    },
    playNoteInMusic: function (step, note, time) {
        this.playNote(this.convertStep(step, note), time);
    },
    playNote: function (name, duration) {
        synth.triggerAttackRelease(name, duration);
    },
    convertStep: function (step, note) {
        var high = 4;
        while (note.endsWith('>')) { note = note.slice(0, -1); high--; }
        while (note.endsWith('<')) { note = note.slice(0, -1); high++; }
        if (step == 'D' && note == '7') high++;
        return this.stepMap[step][Number.parseInt(note) - 1] + high;
    },
    stepMap: {
        "C": ['C', 'D', 'E', 'F', 'G', 'A', 'B'],
        "D": ['D', 'E', 'F#', 'G', 'A', 'B', 'C#']
    },
    error: function (msg) {
        log(msg);
        try {
            for (n in SampleLibrary.piano) this.playNote(n, '2n');
        } catch (ignore) { }
    }
}